#include "../include/thread_pool.h"
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

#define MAX_EVENTS 1024

// 为thread_pool_add_task适配的回调函数包装器
typedef struct
{
    void (*callback)(int);
    int fd;
} callback_wrapper_t;

static void callback_adapter(void *arg)
{
    callback_wrapper_t *wrapper = (callback_wrapper_t *)arg;
    wrapper->callback(wrapper->fd);
    free(wrapper);
}

/**
 * @brief 启动基于epoll的TCP服务器
 * @param port 监听端口号(1024-65535)
 * @param callback 新连接回调函数，参数为客户端文件描述符
 * @details 创建非阻塞式监听socket，使用epoll事件循环处理多连接
 *          支持边缘触发(ET)模式，搭配线程池处理IO事件
 * @warning 需要提前初始化openssl引擎
 */
void start_epoll_server(int port, void (*callback)(int))
{
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr = {0};

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    bind(server_fd, (struct sockaddr *)&addr, sizeof(addr));
    listen(server_fd, 10); // 使用10替代SOMAXCONN

    int epoll_fd = epoll_create1(0);
    struct epoll_event event = {0};
    event.events = EPOLLIN;
    event.data.fd = server_fd;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event);

    // 修正thread_pool_create参数，添加最小线程数、最大线程数和最大队列参数
    thread_pool_t *pool = thread_pool_create(4, 8, 100);

    while (1)
    {
        struct epoll_event events[MAX_EVENTS];
        int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        for (int i = 0; i < n; i++)
        {
            if (events[i].data.fd == server_fd)
            {
                int client_fd = accept(server_fd, NULL, NULL);
                event.data.fd = client_fd;
                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event);
            }
            else
            {
                // 使用适配器函数解决函数签名不匹配问题
                callback_wrapper_t *wrapper = malloc(sizeof(callback_wrapper_t));
                if (wrapper)
                {
                    wrapper->callback = callback;
                    wrapper->fd = events[i].data.fd;
                    thread_pool_add_task(pool, callback_adapter, wrapper);
                }
            }
        }
    }
}